package ru.papergames.view.mediators
{
	import flash.events.Event;
	import mx.collections.ArrayCollection;
	import mx.events.CloseEvent;
	import org.puremvc.as3.interfaces.INotification;
	import ru.papergames.controller.notifications.CoreNotifications;
	import ru.papergames.controller.notifications.FrontendNotifications;
	import ru.papergames.model.binsocket.packets.request.BattleMoveBallRequest;
	import ru.papergames.model.binsocket.packets.request.BattleTurnFinishRequest;
	import ru.papergames.model.binsocket.packets.request.ClientLoadedBattleRequest;
	import ru.papergames.model.proxies.LoginProxy;
	import ru.papergames.model.vo.BallVO;
	import ru.papergames.model.vo.PlayerVO;
	import ru.papergames.model.vo.PopupMessageVO;
	import ru.papergames.model.vo.PositionVO;
	import ru.papergames.utils.helpers.MapHelper;
	import ru.papergames.view.components.AlertText;
	import ru.papergames.view.components.field.BallClip;
	import ru.papergames.view.components.field.FightFieldGrid;
	import ru.papergames.view.events.GameUIEvent;
	import ru.papergames.view.events.LoginEvent;
	import ru.papergames.view.events.PositionSelectEvent;
	import ru.papergames.view.screens.MainUITopView;
	import ru.papergames.model.binsocket.packets.response.*;
	
	
	
	public class MainUITopViewMediator extends BaseMediator
	{
		
		public static const NAME:String = 'MainUITopViewMediator';
		
		private var position_from:PositionVO;
		
		private var cellsToFree:Array = null;
		
		private var ballIsMoving:Boolean = false;
		
		public function MainUITopViewMediator(viewComponent:Object=null)
		{
			super(NAME, viewComponent);
		}
		
		override public function onRegister():void {
			super.onRegister();
			
			view.players = new ArrayCollection( messagingProxy.getPlayers() );
			
			addListeners();
		}
		
		override public function onRemove():void {
			super.onRemove();
			removeListeners();
			
			view.players = null;
			
			grid.actors.removeAllChildren();
			
			this.setViewComponent(null);
		}
		
		protected function get view():MainUITopView {
			return this.viewComponent as MainUITopView;
		}
		
		protected function get grid():FightFieldGrid {
			return view.fightField.fGrid as FightFieldGrid;
		}
				
		
		override public function listNotificationInterests():Array {
			var notes:Array = super.listNotificationInterests();
			
			notes.push( 
					SystemMessageResponse.NO_ACTION_POINTS,
					SystemMessageResponse.NOT_YOUR_TURN,
					SystemMessageResponse.PLAYER_TURN_STARTED,
					SystemMessageResponse.BAD_DISTANCE,
					
					AuthorizationPassedResponse.NOTIFICATION,
					
					NotifyUserBattleCreateFailedResponse.NOTIFICATION,
					
					BattleMemberInfoAboutHimselfResponse.NOTIFICATION,
					BattleMemberListResponse.NOTIFICATION,
					
					BattleMapInfoResponse.NOTIFICATION,
					BattleFinishedResponse.NOTIFICATION,					
					BattlePlayerMovedBallResponse.NOTIFICATION,
					
					BattleNewBallsThrownResponse.NOTIFICATION,
					
					BattleYourTurnEndsResponse.NOTIFICATION,
					BattleYourTurnResponse.NOTIFICATION,
					
					BattlePlayerStartedTurnResponse.NOTIFICATION,
					
					BattleRemoveBallsInLinesResponse.NOTIFICATION,
					BattleIncorrectRouteResponse.NOTIFICATION,
					
					BattleBallNotFoundResponse.NOTIFICATION,
					BattleNotYourBallResponse.NOTIFICATION
					);
			
			return notes;
		}
		
		override public function handleNotification(note:INotification):void {
				
			switch ( note.getName() ) {
				
				case AuthorizationPassedResponse.NOTIFICATION:
					//messagingProxy.send( new ClientLoadedBattleRequest() );
					
					AlertText.show(view.stage, 'Авторизация успешна');
					
					break;
				
				case SystemMessageResponse.NO_ACTION_POINTS:
					
					AlertText.show(view.stage, 'Нет очков действия', 'error');
					
					break;
					
				case SystemMessageResponse.NOT_YOUR_TURN:
					
					AlertText.show(view.stage, 'Сейчас не Ваш ход', 'error');
					
					break;
				
				case SystemMessageResponse.PLAYER_TURN_STARTED:
					
					break;
				
				case SystemMessageResponse.BAD_DISTANCE:
					
					AlertText.show(view.stage, 'Недопустимое расстояние', 'error');
					
					break;
				
				
				case NotifyUserBattleCreateFailedResponse.NOTIFICATION:
					
					facade.sendNotification(
								CoreNotifications.POPUP_MESSAGE, 
								new PopupMessageVO(
									'Не удалось создать бой. Повторите попытку входа в игру.', 
									'Ошибка'
									)
								);
								
					facade.sendNotification(FrontendNotifications.LOGOUT);
					
					break;
				
				
				case BattleMemberInfoAboutHimselfResponse.NOTIFICATION:
					
					var bpahr:BattleMemberInfoAboutHimselfResponse = note.getBody() as BattleMemberInfoAboutHimselfResponse;
										
					messagingProxy.addPlayer(bpahr.player);					
					view.players.source = messagingProxy.getPlayers();
					view.players.refresh();
					
					AlertText.show(view.stage, 'Информация о своем игроке получена');
					
					break;
					
				case BattleMemberListResponse.NOTIFICATION:
					
					var bmlr:BattleMemberListResponse = note.getBody() as BattleMemberListResponse;
										
					messagingProxy.addPlayers(bmlr.players);
					view.players.source = messagingProxy.getPlayers();
					view.players.refresh();
					
					messagingProxy.send(new ClientLoadedBattleRequest());
					
					AlertText.show(view.stage, 'Информация о противниках получена');
					
					break;
				
				
				case BattleMapInfoResponse.NOTIFICATION:
					
					var bmir:BattleMapInfoResponse = note.getBody() as BattleMapInfoResponse;
					
					view.fightField.field_cols = bmir.mapSize.width;
					view.fightField.field_rows = bmir.mapSize.height;
					
					AlertText.show(view.stage, 'Получены данные о боевом поле');
					
					break;
				
				case BattleFinishedResponse.NOTIFICATION:
					
					facade.sendNotification(
								CoreNotifications.POPUP_MESSAGE, 
								new PopupMessageVO(
										'Победила такая-то команда', 
										'Игра окончена', 
										false,
										tryLogout
									)
								);
					
					break;
									
				case BattlePlayerMovedBallResponse.NOTIFICATION:
					
					var bpmbr:BattlePlayerMovedBallResponse = note.getBody() as BattlePlayerMovedBallResponse;
					
					grid.actors.stopBallSelectionAnimation( bpmbr.route[0] );
					
					ballIsMoving = true;
					
					grid.actors.ballMove(bpmbr.route);
					
					break;
					
				case BattleNewBallsThrownResponse.NOTIFICATION:
					
					var bnbtr:BattleNewBallsThrownResponse = note.getBody() as BattleNewBallsThrownResponse;
			
					for each (var bvo:BallVO in bnbtr.balls) {
						addBallToField(bvo);
					}
					
					break;
				
				case BattleYourTurnEndsResponse.NOTIFICATION:
					view.fightField.allow_actions = false;	
					
					grid.actors.stopAllBallsTweening();
					
					AlertText.show(view.stage, 'Ваш ход окончен');
					
					break;
				
				case BattleYourTurnResponse.NOTIFICATION:
					view.fightField.allow_actions = true;
					position_from = null;
					
					AlertText.show(view.stage, 'Ваш ход');
					
					break;
				
				
				case BattlePlayerStartedTurnResponse.NOTIFICATION:
					
					var bpstr:BattlePlayerStartedTurnResponse = note.getBody() as BattlePlayerStartedTurnResponse;
					messagingProxy.setPlayerInTurn(bpstr.playerId);
					
					break;
				
				
				case BattleRemoveBallsInLinesResponse.NOTIFICATION:
					
					var brbilr:BattleRemoveBallsInLinesResponse = note.getBody() as BattleRemoveBallsInLinesResponse;
					
					cellsToFree = brbilr.cellsToBeFree;
					
					break;
				
				case BattleIncorrectRouteResponse.NOTIFICATION:
					
					AlertText.show(view.stage, 'Путь неверен', 'error');
					
					break;
				
				
				case BattleBallNotFoundResponse.NOTIFICATION:
					
					AlertText.show(view.stage, 'Шар не найден', 'error');
					
					break;
					
				case BattleNotYourBallResponse.NOTIFICATION:
					
					AlertText.show(view.stage, 'Передвигайте только свои шары!', 'error');
					
					break;
			}
			
		}
		
		
		/*** PRIVATE IMPLEMENTATION ********/
		
		private function addListeners():void {
			view.addEventListener(LoginEvent.TRY_LOGOUT, tryLogout);
			
			view.addEventListener(GameUIEvent.READY_FOR_BATTLE, readyForBattle);
			view.addEventListener(GameUIEvent.END_TURN, endTurn);
			
			view.addEventListener(PositionSelectEvent.SELECT, positionSelected, true);
			
			view.addEventListener(GameUIEvent.ANIMATION_COMPLETED, ballAnimationComleted, true);
		}
		
		private function removeListeners():void {
			view.removeEventListener(LoginEvent.TRY_LOGOUT, tryLogout);
			
			view.removeEventListener(GameUIEvent.READY_FOR_BATTLE, readyForBattle);
			view.removeEventListener(GameUIEvent.END_TURN, endTurn);
			
			view.removeEventListener(PositionSelectEvent.SELECT, positionSelected, true);
			
			view.removeEventListener(GameUIEvent.ANIMATION_COMPLETED, ballAnimationComleted, true);
		}
		
		
		private function ballAnimationComleted(evt:Event):void {
			//check line erasing queue
			
			ballIsMoving = false;
			
			if (!cellsToFree) return;
			
			for each (var pos:PositionVO in cellsToFree) {
				grid.actors.removeBallAt(pos);
			}
			
			cellsToFree = null;
			
			AlertText.show(view.stage, 'Линия!!!');
			
		}
		
		private function endTurn(evt:Event):void {
			messagingProxy.send( new BattleTurnFinishRequest() );
		}
		
		
		private function readyForBattle(evt:Event):void {
			messagingProxy.joinToPlayersPool();
		}
		
		private function positionSelected(evt:PositionSelectEvent):void {
			
			//check movements!
			if ( ballIsMoving ) return;
			
								
			//play selected if this is new pos or send route if cell is free
			var myPlayer:PlayerVO = messagingProxy.getMyPlayer();
			var myPlayerColorId:int = myPlayer ? myPlayer.coloreId : -1;
			
			var ballAtPosition:BallClip = grid.actors.getBallClip(evt.position);
			
			if ( ballAtPosition && ballAtPosition.data.coloreId == myPlayerColorId )  {
				
				if (position_from) grid.actors.stopBallSelectionAnimation(position_from);
				
				position_from = evt.position;
				grid.actors.playBallSelectionAnimation(position_from);
				
			} else if (!ballAtPosition && position_from) {
				
				var route:Array = MapHelper.make_path(
											position_from, 
											evt.position, 
											view.fightField.field_cols,
											view.fightField.field_rows, 
											grid.actors.getBusyPositions(position_from)
											);
											
				route.unshift(position_from);
				
				var req:BattleMoveBallRequest = new BattleMoveBallRequest( route );
															
				messagingProxy.send(req);
				
			}
			
		}
		
		private function tryLogout(evt:Event):void {
			facade.sendNotification(FrontendNotifications.LOGOUT);
		}
		
		
		private function addBallToField(data:BallVO):void {
			
			var ball:BallClip = new BallClip(data);
			
			grid.actors.addChild(ball);
		}
		
		
	}
}